#include "SpriteDirectDraw.h"

#include "SurfaceDirectDraw.h"

namespace YoghurtGum
{

	SpriteDirectDraw::SpriteDirectDraw() : Sprite()
	{
		m_TargetSurface = RenderMethodDirectDraw::GetSingleton()->GetBackBuffer();
		m_TargetObject = RenderMethodDirectDraw::GetSingleton()->GetObject();
		m_Properties = 0;
	}

	SpriteDirectDraw::~SpriteDirectDraw()
	{

	}

	void SpriteDirectDraw::SetAlphaKey(Color a_AlphaKey)
	{
		//COLORREF key = a_AlphaKey.GetColorCOLORREF();
		COLORREF key = a_AlphaKey.GetColor();
		//Log::Print("Color key: 0x%x (%.2f, %.2f, %.2f)", key, a_AlphaKey.r, a_AlphaKey.g, a_AlphaKey.b);

		//key = RGB(255, 0, 255);
		m_AlphaKey.dwColorSpaceLowValue     = key;
		m_AlphaKey.dwColorSpaceHighValue    = key;
	}	

	bool SpriteDirectDraw::Draw(float a_X, float a_Y, float a_Depth)
	{
		CopyRect(&m_Target, &m_Dimensions);
		OffsetRect(&m_Target, (int32)a_X, (int32)a_Y);

		LPDIRECTDRAWSURFACE target = RenderMethodDirectDraw::GetSingleton()->GetBackBuffer();

		if (a_X < 0.f || a_Y < 0.f)
		{
			LPDIRECTDRAWCLIPPER clipper = NULL;
			target->GetClipper(&clipper);
			if (!clipper)
			{
				ERROR_EXPLAIN("Trying to draw a sprite outside the surface but no clipper is attached.");
				return false;
			}
		}
		uint32 backwidth = RenderMethodDirectDraw::GetSingleton()->GetBackbufferWidth();
		if (m_Target.left > 0 && (uint32)m_Target.left >= backwidth) { return false; }
		if (m_Target.right <= 0) { return false; }

		uint32 backheight = RenderMethodDirectDraw::GetSingleton()->GetBackbufferHeight();
		if (m_Target.top > 0 && (uint32)m_Target.top >= backheight) { return false; }
		if (m_Target.bottom <= 0) { return false; }

		if (m_Properties & YG_SPRITE_TRANSPARANCY_KEYING)
		{
			if (ErrorDirectDraw::Failed(target->Blt (
						&m_Target,
						m_Surf,
						&m_Dimensions,
						DDBLT_KEYSRC,
						NULL
					)
				)
			)
			{
				ERROR_EXPLAIN("Failed to copy sprite to backbuffer. (Target: (%i %i %i %i))", m_Target.left, m_Target.top, m_Target.right, m_Target.bottom);
				return false;
			}
		}
		else
		{
			if (ErrorDirectDraw::Failed(target->Blt (
						&m_Target,
						m_Surf,
						&m_Dimensions,
						NULL,
						NULL
					)
				)
			)
			{
				ERROR_EXPLAIN("Failed to copy sprite to backbuffer. (%i, %i, %i, %i)", m_Target.left, m_Target.top, m_Target.right, m_Target.bottom);
				return false;
			}
		}

		return true;
	}

	Surface* SpriteDirectDraw::ToSurface()
	{
		SurfaceDirectDraw* result = new SurfaceDirectDraw(m_Dimensions.bottom, m_Dimensions.right);

		DDSURFACEDESC desc;
		ZeroMemory(&desc, sizeof(desc));
		desc.dwSize = sizeof(desc);

		if (ErrorDirectDraw::Failed(m_Surf->Lock(
					NULL,
					&desc, 
					0, 
					NULL
				)
			)
		)
		{
			ERROR_EXPLAIN("Failed to lock surface.");
			return NULL;
		}

		result->SetBuffer((YGC*)desc.lpSurface);

		if (ErrorDirectDraw::Failed(m_Surf->Unlock(
					NULL
				)
			)
		)
		{
			ERROR_EXPLAIN("Failed to unlock surface.");
			return NULL;
		}

		return result;
	}

	bool SpriteDirectDraw::SetData(ImageData* a_Data)
	{
		m_Properties = a_Data->props;

		CopyRect(&m_Dimensions, &a_Data->dim);

		if (ErrorDirectDraw::Failed(m_TargetObject->CreateSurface (
					&a_Data->desc,
					&m_Surf,
					NULL
				)
			)
		)
		{
			ERROR_EXPLAIN("Failed to create sprite surface.");
			return false;
		}

		if (ErrorDirectDraw::Failed(m_Surf->Blt(
					&a_Data->dim,
					a_Data->surf,
					NULL,
					NULL,
					NULL
				)
			)
		)
		{
			ERROR_EXPLAIN("Failed to copy surface.");
			return false;
		}

		if (m_Properties & YG_SPRITE_TRANSPARANCY_KEYING)
		{
			SetAlphaKey(a_Data->key);
			m_Surf->SetColorKey(DDCKEY_SRCBLT, &m_AlphaKey);
		}

		return true;
	}

}; // namespace YoghurtGum
